/**
 * @file   USB2XXX_CAN_DBCParser.cpp
 * @brief  解析DBC文件，并通过DBC文件进行数据解析和收发，测试前先将CAN1和CAN2对接
 * @author wdluo(wdluo@toomoss.com)
 * @version 1.0
 * @date 2022-12-03
 * @copyright Copyright (c) 2022 重庆图莫斯电子科技有限公司
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "usb_device.h"
#include "usb2can.h"
#include "dbc_parser.h"
#if _WIN32
#include <windows.h>
#pragma comment(lib,"USB2XXX.lib")
#endif

int main(int argc, const char* argv[])
{
    DEVICE_INFO DevInfo;
    int DevHandle[10];
    int SendCANIndex = 0;//0-CAN1,1-CAN2
    int ReadCANIndex = 1;//0-CAN1,1-CAN2
    bool state;
    int ret;
    //扫描连接到电脑的设备，并获取设备号
    ret = USB_ScanDevice(DevHandle);
    if(ret <= 0){
        printf("No device connected!\n");
        return 0;
    }
    //打开设备
    state = USB_OpenDevice(DevHandle[0]);
    if(!state){
        printf("Open device error!\n");
        return 0;
    }
    char FunctionStr[256]={0};
    //获取设备固件信息
    state = DEV_GetDeviceInfo(DevHandle[0],&DevInfo,FunctionStr);
    if(!state){
        printf("Get device infomation error!\n");
        return 0;
    }else{
        printf("Firmware Info:\n");
	    printf("Firmware Name:%s\n",DevInfo.FirmwareName);
        printf("Firmware Build Date:%s\n",DevInfo.BuildDate);
        printf("Firmware Version:v%d.%d.%d\n",(DevInfo.FirmwareVersion>>24)&0xFF,(DevInfo.FirmwareVersion>>16)&0xFF,DevInfo.FirmwareVersion&0xFFFF);
        printf("Hardware Version:v%d.%d.%d\n",(DevInfo.HardwareVersion>>24)&0xFF,(DevInfo.HardwareVersion>>16)&0xFF,DevInfo.HardwareVersion&0xFFFF);
    }
    //解析DBC文件，注意DBC文件路径要对，否则可能不能正常解析
    long long DBCHandle = DBC_ParserFile(DevHandle[0],"demo.dbc");
    if(DBCHandle==NULL){
        printf("Parser DBC File error!\n");
        return 0;
    }else{
        printf("Parser DBC File success!\n");
    }
    //获取消息名称和信号名称并打印出来
    int DBCMsgNum = DBC_GetMsgQuantity(DBCHandle);
    for(int i=0;i<DBCMsgNum;i++) {
        char MsgName[64]={0};
        DBC_GetMsgName(DBCHandle,i,MsgName);
        printf("Msg.Name = %s\n",MsgName);
        int DBCSigNum = DBC_GetMsgSignalQuantity(DBCHandle,MsgName);
        printf("Signals:\n");
        for(int j=0;j<DBCSigNum;j++) {
            char SigName[64]={0};
            DBC_GetMsgSignalName(DBCHandle,MsgName,j,SigName);
            printf("\t%s \n",SigName);
        }
        printf("\n");
    }
    //获取CAN波特率参数并初始化配置CAN
    CAN_INIT_CONFIG CANConfig;
    ret = CAN_GetCANSpeedArg(DevHandle[0],&CANConfig,500000);
    if(ret != CAN_SUCCESS){
        printf("Get CAN Speed Arg Failed!\n");
        return 0;
    }else{
        printf("Get CAN Speed Arg Success!\n");
    }
    ret = CAN_Init(DevHandle[0],SendCANIndex,&CANConfig);
    if(ret != CAN_SUCCESS){
        printf("Config CAN failed!\n");
        return 0;
    }else{
        printf("Config CAN Success!\n");
    }
    ret = CAN_Init(DevHandle[0],ReadCANIndex,&CANConfig);
    if(ret != CAN_SUCCESS){
        printf("Config CAN failed!\n");
        return 0;
    }else{
        printf("Config CAN Success!\n");
    }
    CAN_MSG CanMsg[3];
    //设置信号值，注意需要根据自己的DBC文件修改帧名称，信号名称，以及对应的值
    DBC_SetSignalValue(DBCHandle,"msg_moto_speed","moto_speed",2412);
    DBC_SetSignalValue(DBCHandle,"msg_oil_pressure","oil_pressure",980);
    DBC_SetSignalValue(DBCHandle,"msg_speed_can","speed_can",120);
    //将信号值同步到CAN消息里面
    DBC_SyncValueToCANMsg(DBCHandle,"msg_moto_speed",&CanMsg[0]);
    DBC_SyncValueToCANMsg(DBCHandle,"msg_oil_pressure",&CanMsg[1]);
    DBC_SyncValueToCANMsg(DBCHandle,"msg_speed_can",&CanMsg[2]);
    //发送CAN消息，这些消息里面就包含了前面设置的信号值
    int SendedNum = CAN_SendMsg(DevHandle[0],SendCANIndex,CanMsg,3);
    if(SendedNum >= 0){
        printf("Success send frames:%d\n",SendedNum);
    }else{
        printf("Send CAN data failed! %d\n",SendedNum);
    }
    //读取CAN消息并打印输出原始数据
    CAN_MSG CanMsgBuffer[10];
    int CanNum = CAN_GetMsg(DevHandle[0],ReadCANIndex,CanMsgBuffer);
    if(CanNum > 0){
        printf("CanNum = %d\n",CanNum);
        for(int i=0;i<CanNum;i++){
            printf("CanMsg[%d].ID = 0x%08X\n",i,CanMsgBuffer[i].ID);
            printf("CanMsg[%d].TimeStamp = %d\n",i,CanMsgBuffer[i].TimeStamp);
            printf("CanMsg[%d].Data = ",i);
            for(int j=0;j<CanMsgBuffer[i].DataLen;j++){
                printf("%02X ",CanMsgBuffer[i].Data[j]);
            }
            printf("\n");
        }
    }else if(CanNum == 0){
        printf("No CAN data!\n");
    }else{
        printf("Get CAN data error!\n");
    }
    //将CAN消息同步到DBC解析器里面
    DBC_SyncCANMsgToValue(DBCHandle,CanMsgBuffer,CanNum);
    //读取解析器里面信号值，并打印显示出来
    char ValueStr[128];
    ret = DBC_GetSignalValueStr(DBCHandle,"msg_moto_speed","moto_speed",ValueStr);
    if(ret == DBC_PARSER_OK){
        printf("moto_speed = %s\n",ValueStr);
    }else{
        printf("Get Signal Value Error ret = %d\n",ret);
    }
    
    ret = DBC_GetSignalValueStr(DBCHandle,"msg_oil_pressure","oil_pressure",ValueStr);
    if(ret == DBC_PARSER_OK){
        printf("oil_pressure = %s\n",ValueStr);
    }else{
        printf("Get Signal Value Error ret = %d\n",ret);
    }
    
    ret = DBC_GetSignalValueStr(DBCHandle,"msg_speed_can","speed_can",ValueStr);
    if(ret == DBC_PARSER_OK){
        printf("speed_can = %s\n",ValueStr);
    }else{
        printf("Get Signal Value Error ret = %d\n",ret);
    }
    
	return 0;
}

